{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# HTTP request to ZhipuAI GLM API\n",
    "\n",
    "**This tutorial is available in English and is attached below the Chinese explanation**\n",
    "\n",
    "首先，从最简单的 http 请求开始访问 ZhipuAI 的 GLM 模型的API。 填写完API_KEY后，按照[官方文档](https://open.bigmodel.cn/dev/api#nosdk)的步骤，设计一个简单的http鉴权请求。\n",
    "\n",
    "First, start with the simplest http request to access the API of the ZhipuAI's GLM model. After filling in the API_KEY, follow the steps of [Official Document](https://open.bigmodel.cn/dev/api#nosdk) to design a simple http authentication request."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "446bb790af782d79"
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [],
   "source": [
    "import os\n",
    "os.environ[\"ZHIPUAI_API_KEY\"] = \"your api key\""
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-01-22T14:30:09.689535Z",
     "start_time": "2024-01-22T14:30:09.685928Z"
    }
   },
   "id": "d6e5c89306e3ea8a"
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [],
   "source": [
    "import requests\n",
    "import jwt\n",
    "import time\n",
    "\n",
    "def generate_token(apikey: str, exp_seconds: int):\n",
    "    try:\n",
    "        id, secret = apikey.split(\".\")\n",
    "    except Exception as e:\n",
    "        raise Exception(\"invalid apikey\", e)\n",
    "\n",
    "    payload = {\n",
    "        \"api_key\": id,\n",
    "        \"exp\": int(round(time.time() * 1000)) + exp_seconds * 1000,\n",
    "        \"timestamp\": int(round(time.time() * 1000)),\n",
    "    }\n",
    "\n",
    "    return jwt.encode(\n",
    "        payload,\n",
    "        secret,\n",
    "        algorithm=\"HS256\",\n",
    "        headers={\"alg\": \"HS256\", \"sign_type\": \"SIGN\"},\n",
    "    )"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-01-22T14:30:09.739551Z",
     "start_time": "2024-01-22T14:30:09.691001Z"
    }
   },
   "id": "d4795ec08b8ac562"
  },
  {
   "cell_type": "markdown",
   "source": [
    "接着，我们将函数应用到请求中，并直接执行请求\n",
    "\n",
    "Next, we apply the function to the request and execute the request directly"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "646612397562e5e8"
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [],
   "source": [
    "api_key = os.environ[\"ZHIPUAI_API_KEY\"]\n",
    "token = generate_token(api_key, 60)\n",
    "url = \"https://open.bigmodel.cn/api/paas/v4/chat/completions\"\n",
    "headers = {\n",
    "    \"Content-Type\": \"application/json\",\n",
    "    \"Authorization\": f\"Bearer {token}\"\n",
    "}\n",
    "\n",
    "data = {\n",
    "    \"model\": \"glm-4\",\n",
    "    \"messages\": [\n",
    "        {\n",
    "            \"role\": \"system\",\n",
    "            \"content\": \"your are a helpful assistant\"\n",
    "        },\n",
    "        {\n",
    "            \"role\": \"user\",\n",
    "            \"content\": \"can you tell me a joke?\"\n",
    "        }\n",
    "    ],\n",
    "    \"max_tokens\": 8192,\n",
    "    \"temperature\": 0.8,\n",
    "    \"stream\": False\n",
    "}\n",
    "\n",
    "response = requests.post(url, headers=headers, json=data)\n",
    "ans = response.json()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-01-22T14:30:10.812800Z",
     "start_time": "2024-01-22T14:30:09.740661Z"
    }
   },
   "id": "a11657617389fa01"
  },
  {
   "cell_type": "markdown",
   "source": [
    "接着，我们就得到模型的返回\n",
    "\n",
    "Then, we get the return of the model"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "efec38ed395b7e4b"
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "data": {
      "text/plain": "{'choices': [{'finish_reason': 'stop',\n   'index': 0,\n   'message': {'content': \"Sure! Here's a light-hearted joke for you:\\n\\nWhy don't scientists trust atoms?\\n\\nBecause they make up everything!\",\n    'role': 'assistant'}}],\n 'created': 1705933810,\n 'id': '8313804547540260859',\n 'model': 'glm-4',\n 'request_id': '8313804547540260859',\n 'usage': {'completion_tokens': 26, 'prompt_tokens': 19, 'total_tokens': 45}}"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ans"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-01-22T14:30:10.817649Z",
     "start_time": "2024-01-22T14:30:10.814539Z"
    }
   },
   "id": "867835319ab4ebd5"
  },
  {
   "cell_type": "markdown",
   "source": [
    "我们可以这样获取返回的内容和ID\n",
    "\n",
    "We can get the returned content and ID like this"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "1fe9e3db041ff45b"
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "content: Sure! Here's a light-hearted joke for you:\n",
      "\n",
      "Why don't scientists trust atoms?\n",
      "\n",
      "Because they make up everything!\n",
      "===============\n",
      "id: 8313804547540260859\n"
     ]
    }
   ],
   "source": [
    "print(\"content:\", ans[\"choices\"][0][\"message\"][\"content\"])\n",
    "print(\"===============\")\n",
    "print(\"id:\", ans[\"id\"])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-01-22T14:30:10.821886Z",
     "start_time": "2024-01-22T14:30:10.818917Z"
    }
   },
   "id": "55cd72019020c03e"
  },
  {
   "cell_type": "markdown",
   "source": [
    "如果我想用流式输出，该怎么办呢？我们只需要将`data`中的 `stream`设置为`True`即可！\n",
    "\n",
    "What should I do if I want to use streaming output? We just need to set `stream` in `data` to `True`!"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "6712fd32970c3200"
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sure|!| Here|'s| a| light|-hearted| joke| for| you|:\n",
      "\n",
      "Why| don|'t| scientists| trust| atoms|?\n",
      "\n",
      "Because| they| make| up| everything|!||"
     ]
    }
   ],
   "source": [
    "import json\n",
    "\n",
    "api_key = os.environ[\"API_KEY\"]\n",
    "token = generate_token(api_key, 60)\n",
    "url = \"https://open.bigmodel.cn/api/paas/v4/chat/completions\"\n",
    "headers = {\n",
    "    \"Content-Type\": \"application/json\",\n",
    "    \"Authorization\": f\"Bearer {token}\"\n",
    "}\n",
    "\n",
    "data[\"stream\"] = True\n",
    "response = requests.post(url, headers=headers, json=data)\n",
    "for chunk in response.iter_lines():\n",
    "    if chunk:\n",
    "        chunk_str = chunk.decode('utf-8')\n",
    "        json_start_pos = chunk_str.find('{\"id\"')\n",
    "        if json_start_pos != -1:\n",
    "            json_str = chunk_str[json_start_pos:]\n",
    "            json_data = json.loads(json_str)\n",
    "            for choice in json_data.get('choices', []):\n",
    "                delta = choice.get('delta', {})\n",
    "                content = delta.get('content', '')\n",
    "                print(content, end='|') # I use | to separate the content"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-01-22T14:30:11.768911Z",
     "start_time": "2024-01-22T14:30:10.821131Z"
    }
   },
   "id": "a988a90a62532de"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
